package com.yds.longlinks.client;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import java.lang.ref.WeakReference;
import java.net.InetSocketAddress;

/**
 * 作者:     YDS
 * 创建时间: 2022/11/28 21:02
 * 页面描述: 封装好链接管理供外层调用
 */
public class MinaClientConnectionManager {
    public static final String BROADCAST_ACTION = "com.yds.client";
    public static final String MESSAGE = "message";

    private MinaClientConnectionConfig mConfig;
    private WeakReference<Context> mContext;
    private NioSocketConnector mConnection;
    private IoSession mSession;
    private InetSocketAddress mAddress;

    public MinaClientConnectionManager(MinaClientConnectionConfig config) {
        this.mConfig = config;
        this.mContext = new WeakReference<>(config.getContext());
        init();
    }

    private void init() {
        // 根据主机名和端口号创建地址对象
        mAddress = new InetSocketAddress(mConfig.getIp(), mConfig.getPort());
        mConnection = new NioSocketConnector();
        mConnection.getSessionConfig().setReceiveBufferSize(mConfig.getReadBufferSize());
        mConnection.getFilterChain().addLast("logging", new LoggingFilter());
        mConnection.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
        // 业务处理类
        mConnection.setHandler(new DefaultHandler(mContext.get()));
        // 为连接对象设置默认远程地址(必须)
        mConnection.setDefaultRemoteAddress(mAddress);
    }

    private static class DefaultHandler extends IoHandlerAdapter {
        private Context mContext;

        DefaultHandler(Context context) {
            this.mContext = context;
        }

        @Override
        public void sessionCreated(IoSession session) throws Exception {
            super.sessionCreated(session);
        }

        @Override
        public void sessionOpened(IoSession session) throws Exception {
            // 将session保存到session manager类中，从而可以发送消息到服务器
            MinaClientSessionManager.getInstance().setSession(session);
        }

        @Override
        public void messageReceived(IoSession session, Object message) throws Exception {
            if (null != mContext) {
                Intent intent = new Intent(BROADCAST_ACTION);
                intent.putExtra(MESSAGE, message.toString());
                mContext.sendBroadcast(intent);
            }
        }

        @Override
        public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
            super.exceptionCaught(session, cause);
            Log.i("Simon", "exceptionCaught = " + cause.getMessage());
            // 对等方重置连接
            if (cause.getMessage().equals("Connection reset by peer")) {

            }
        }
    }

    /**
     * 服务器-连接
     *
     * @return
     */
    public boolean connect() {
        try {
            Log.i("Simon", "address = " + mConfig.getIp() + " " + mConfig.getPort());
            ConnectFuture connectFuture = mConnection.connect(new InetSocketAddress(mConfig.getIp(), mConfig.getPort()));
            connectFuture.addListener(new IoFutureListener<ConnectFuture>() {
                @Override
                public void operationComplete(ConnectFuture ioFuture) {
                    Log.i("Simon", "服务器-isConnected = " + ioFuture.isConnected());
                    if (ioFuture.isConnected()) {
                        mSession = connectFuture.getSession();
                        Log.i("Simon", "服务器-mSession = " + mSession);
                        // 将获取到的 Session 保存在 SessionManager 中
                        MinaClientSessionManager.getInstance().setSession(mSession);
                    }
                }
            });
            // 一直尝试连接直到成功
            connectFuture.awaitUninterruptibly(1000);
        } catch (Exception e) {
            Log.i("Simon", "服务器-连接Exception = " + e.getMessage());
            return false;
        }

        return null != mSession;
    }

    /**
     * 断开-服务器-连接
     *
     * @return
     */
    public boolean disConnect() {
        try {
            mConnection.dispose();
            mConnection = null;
            mSession = null;
            mAddress = null;
            mContext = null;
        } catch (Exception e) {
            return false;
        }

        return true;
    }


}
